package cn.minhx.domain.trade.service.settlement;

import cn.minhx.domain.trade.adapter.port.ITradePort;
import cn.minhx.domain.trade.adapter.repostitory.ITradeRepository;
import cn.minhx.domain.trade.moedel.aggregate.GroupBuyTeamSettlementAggregate;
import cn.minhx.domain.trade.moedel.entity.*;
import cn.minhx.domain.trade.moedel.valobj.NotifyTaskHTTPEnumVO;
import cn.minhx.domain.trade.service.ITradeSettlementOrderService;
import cn.minhx.domain.trade.service.settlement.factor.TradeSettlementRuleFilterFactory;
import cn.minhx.types.design.link.multi.chain.BusinessLinkedList;
import com.alibaba.fastjson.JSON;
import jakarta.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

/**
 * 拼团交易结算服务
 *
 * @author min
 */
@Slf4j
@Service
public class TradeSettlementOrderService implements ITradeSettlementOrderService {

	@Resource
	private ITradeRepository repository;
	@Resource
	private ITradePort port;
	@Resource
	private BusinessLinkedList<TradeSettlementRuleCommandEntity, TradeSettlementRuleFilterFactory.DynamicContext, TradeSettlementRuleFilterBackEntity> tradeSettlementRuleFilter;

	@Override
	public TradePaySettlementEntity settlementMarketPayOrder(TradePaySuccessEntity tradePaySuccessEntity)
			throws Exception {
		log.info("拼团交易-支付订单结算:{} outTradeNo:{}", tradePaySuccessEntity.getUserId(),
				tradePaySuccessEntity.getOutTradeNo());

		// 1. 结算规则过滤
		TradeSettlementRuleFilterBackEntity tradeSettlementRuleFilterBackEntity = tradeSettlementRuleFilter.apply(
				TradeSettlementRuleCommandEntity.builder().source(tradePaySuccessEntity.getSource())
						.channel(tradePaySuccessEntity.getChannel()).userId(tradePaySuccessEntity.getUserId())
						.outTradeNo(tradePaySuccessEntity.getOutTradeNo())
						.outTradeTime(tradePaySuccessEntity.getOutTradeTime()).build(),
				new TradeSettlementRuleFilterFactory.DynamicContext());

		String teamId = tradeSettlementRuleFilterBackEntity.getTeamId();

		// 2. 组团信息
		GroupBuyTeamEntity groupBuyTeamEntity = GroupBuyTeamEntity.builder()
				.teamId(tradeSettlementRuleFilterBackEntity.getTeamId())
				.activityId(tradeSettlementRuleFilterBackEntity.getActivityId())
				.targetCount(tradeSettlementRuleFilterBackEntity.getTargetCount())
				.completeCount(tradeSettlementRuleFilterBackEntity.getCompleteCount())
				.lockCount(tradeSettlementRuleFilterBackEntity.getLockCount())
				.status(tradeSettlementRuleFilterBackEntity.getStatus())
				.validStartTime(tradeSettlementRuleFilterBackEntity.getValidStartTime())
				.validEndTime(tradeSettlementRuleFilterBackEntity.getValidEndTime())
				.notifyUrl(tradeSettlementRuleFilterBackEntity.getNotifyUrl()).build();
		// 3. 构建聚合对象
		GroupBuyTeamSettlementAggregate groupBuyTeamSettlementAggregate = GroupBuyTeamSettlementAggregate.builder()
				.userEntity(UserEntity.builder().userId(tradePaySuccessEntity.getUserId()).build())
				.groupBuyTeamEntity(groupBuyTeamEntity).tradePaySuccessEntity(tradePaySuccessEntity).build();
		// 4. 拼团交易结算
		boolean isNotify = repository.settlementMarketPayOrder(groupBuyTeamSettlementAggregate);

		// 5. 组队回调处理 - 处理失败也会有定时任务补偿，通过这样的方式，可以减轻任务调度，提高时效性
		if (isNotify) {
			Map<String, Integer> notifyResultMap = execSettlementNotifyJob(teamId);
			log.info("回调通知拼团完结 result:{}", JSON.toJSONString(notifyResultMap));
		}

		// 6. 返回结算信息
		return TradePaySettlementEntity.builder().source(tradePaySuccessEntity.getSource())
				.channel(tradePaySuccessEntity.getChannel()).userId(tradePaySuccessEntity.getUserId()).teamId(teamId)
				.activityId(groupBuyTeamEntity.getActivityId()).outTradeNo(tradePaySuccessEntity.getOutTradeNo())
				.build();
	}

	@Override
	public Map<String, Integer> execSettlementNotifyJob() throws Exception {
		log.info("拼团交易-执行结算通知任务");

		// 查询未执行任务
		List<NotifyTaskEntity> notifyTaskEntityList = repository.queryUnExecutedNotifyTaskList();

		return execSettlementNotifyJob(notifyTaskEntityList);
	}

	@Override
	public Map<String, Integer> execSettlementNotifyJob(String teamId) throws Exception {
		log.info("拼团交易-执行结算通知回调，指定 teamId:{}", teamId);
		List<NotifyTaskEntity> notifyTaskEntityList = repository.queryUnExecutedNotifyTaskList(teamId);
		return execSettlementNotifyJob(notifyTaskEntityList);
	}

	private Map<String, Integer> execSettlementNotifyJob(List<NotifyTaskEntity> notifyTaskEntityList) throws Exception {
		int successCount = 0, errorCount = 0, retryCount = 0;
		for (NotifyTaskEntity notifyTask : notifyTaskEntityList) {
			// 回调处理 success 成功，error 失败
			String response = port.groupBuyNotify(notifyTask);

			// 更新状态判断&变更数据库表回调任务状态
			if (NotifyTaskHTTPEnumVO.SUCCESS.getCode().equals(response)) {
				int updateCount = repository.updateNotifyTaskStatusSuccess(notifyTask.getTeamId());
				if (1 == updateCount) {
					successCount += 1;
				}
			} else if (NotifyTaskHTTPEnumVO.ERROR.getCode().equals(response)) {
				if (notifyTask.getNotifyCount() < 5) {
					int updateCount = repository.updateNotifyTaskStatusError(notifyTask.getTeamId());
					if (1 == updateCount) {
						errorCount += 1;
					}
				} else {
					int updateCount = repository.updateNotifyTaskStatusRetry(notifyTask.getTeamId());
					if (1 == updateCount) {
						retryCount += 1;
					}
				}
			}
		}

		Map<String, Integer> resultMap = new HashMap<>();
		resultMap.put("waitCount", notifyTaskEntityList.size());
		resultMap.put("successCount", successCount);
		resultMap.put("errorCount", errorCount);
		resultMap.put("retryCount", retryCount);

		return resultMap;
	}
}
